package logica;

import java.util.Iterator;

import java.util.LinkedList;
import java.util.List;

import logica.persistencia.ObjetoDiagramaPersistente;
import logica.persistencia.RelacionPersistente;
import memento.IMemento;
import memento.MementoRelacionLogica;

public class Relacion extends ObjetoDiagramaConAtributo
{
	private List<EntidadRol> entidades;
	private TipoDeRelacion tipo;
	
	public Relacion(String nombre, List<EntidadRol> entidadesRol) throws RelacionException, SinNombreException
	{
		super(nombre);
		
		this.setEntidadesRol(entidadesRol);
		this.setTipo(TipoDeRelacion.NO_DEFINIDO);
	}
	
	public void agregarEntidadRol(EntidadRol entidad) throws RelacionException
	{
		verificarSiEntidadRolRepetida(entidad);
		this.getEntidades().add(entidad);
	}

	private void verificarSiEntidadRolRepetida(EntidadRol entidad) throws RelacionException 
	{
		Iterator<EntidadRol> itEntidad = this.getEntidades().iterator();
		
		while (itEntidad.hasNext())
		{
			if (entidad.equals(itEntidad.next()))
				throw new RelacionException("No se puede agregar la entidad " + entidad.getEntidad() + " por que ya esta incluida en la relacion y con el mismo rol.");
		}
	}
	
	public void agregarEntidadesRol(List<EntidadRol> entidadesRol) throws RelacionException
	{
		if (entidadesRol.size() < 2)
			throw new RelacionException("Una relacion debe vincular dos o mas entidades distintas o bien una entidad consigo misma pero con distintos roles.");
		
		Iterator<EntidadRol> itEntidades = entidadesRol.iterator();
		
		while (itEntidades.hasNext())
			this.agregarEntidadRol(itEntidades.next());
	}
	
	// borra las entidades-rol que podría llegar a tener
	public void setEntidadesRol(List<EntidadRol> entidadesRol) throws RelacionException
	{
		this.entidades = new LinkedList<EntidadRol>();
		
		this.agregarEntidadesRol(entidadesRol);
	}

	@Override
	public List<Entidad> getReferenciaAEntidadesExternas()
	{
		List<Entidad> referencias = new LinkedList<Entidad>();
		Iterator<EntidadRol> iterador = getEntidades().iterator();
		
		while (iterador.hasNext())
			referencias.add(iterador.next().getEntidad());
		
		return referencias;
	}
	
	public void setTipo(TipoDeRelacion tipo) {
		this.tipo = tipo;
	}

	public TipoDeRelacion getTipo() {
		return tipo;
	}
	
	public ObjetoDiagramaPersistente getObjetoDiagramaPersistente() {
		return new RelacionPersistente(this);
	}

	public List<EntidadRol> getEntidades() {
		return entidades;
	}

	@Override
	public boolean tieneEstaEntidad(Entidad entidad) {
		
		for (EntidadRol	entRol: this.getEntidades())
		{
			if (entRol.tieneEstaEntidad(entidad))
				return true;
		}
		
		return false;
	}

	@Override
	public IMemento getMementoEspecializado() {
		return new MementoRelacionLogica(this);
	}

	@Override
	public void saveMemento(IMemento memento) {
		memento.cargarMemento();		
	}
	
	public boolean esRelacionFuerteDebil() 
	{
		if (this.getEntidades().size() != 2)
			return false;
		
		for (EntidadRol entidadRolFuerte: this.getEntidades())
			for (EntidadRol entidadRolDebil: this.getEntidades())
				if (entidadRolDebil.getEntidad().tieneEstaEntidad(entidadRolFuerte.getEntidad()))
					return true;

		return false;
	}
}
